#ifndef _TIPOH
#define _TIPOH

#include <string>
#include <memory>

using namespace std;

/******************************************************** 
Enumeración de los tipos de simbolos de la tabla:
En nuestra implementación tenemos:
	ENTERO
	FUNCION
	VOID
*********************************************************/
enum TipoValor { 
  ENTERO,
  CARACTER, 
  FLOAT,
  VOID,
  ERROR,
  CTECADENA  
};

/*
La clase virtual tipo implementa el tipo de cualquier nodo del árbol 
sintáctico. Para ello, el tipo Nodo agrega una instancia de tipo 
*/
class Tipo{
public:

/*
La función virtual pura nombre obliga a cualquier clase que extienda a tipo
que devuelva un string con el nombre del tipo
*/
TipoValor claveTipo;
virtual string nombre()=0;

};

/*
El tipo entero corresponde con el int de C
*/
class TipoEntero: public Tipo{

public:
/* inicializa el tipo con la clave que le corresponde */
TipoEntero() {claveTipo=ENTERO;}
/* Implementa la función virtual nombre() */
string nombre() {return string("int");}

};


/*
El tipo char corresponde con el char de C
*/
class TipoChar: public Tipo{
public:
/* inicializa el tipo con la clave que le corresponde */
TipoChar() {claveTipo=CARACTER;}
/* Implementa la función virtual nombre() */
string nombre(){return string("char");}

};

/*
EL tipo float corresponde con el float de C
*/
class TipoFloat: public Tipo {

public:
/* inicializa el tipo con la clave que le corresponde */
TipoFloat() {claveTipo=FLOAT;}
/* Implementa la función virtual nombre() */
string nombre() {return string("float");}

};


/*
La clase tipoError es un tipo que se asigna a cualquier nodo donde se produzca 
un error de incompatilidad de tipos.
*/
class TipoError: public Tipo{

private:

/*msg almacena el mensaje explicativo del error detectado */
string msg;

public:

/*Constructor que inicializa un objeto tipoError con un mensaje proporcionado
  a través del parámero m , y lo inicializa con la clave que le corresponde*/
TipoError(string m=""):msg(m){claveTipo=ERROR;}

/* Implementa la función virtual nombre() */
string nombre(){return string("error");}

/* Funcion inline que devuelve el mensaje explicativo del error detectado */
string mensaje(){return msg;}

/* Sobercarga del operador asignación para tipoEror */
TipoError& operator= (TipoError& te)
{ 
  msg=te.mensaje();
  return *this;
}

};

/* Implementa el tipo constante cadena */
class TipoConstanteCadena : public Tipo {

public:
TipoConstanteCadena() {claveTipo=CTECADENA;}
string nombre() {return string("cteCadena");}

};

/* Implementa el tipo void */
class TipoVoid : public Tipo {

public:
/* inicializa el tipo con la clave que le corresponde */
TipoVoid() {claveTipo=VOID;}
string nombre() {return string("void");}

};


// Campos de este tipo nos garantizan que la memoria se libera bien
// El campo tipo lo utilizamos para el manejo seguro de un puntero 
// a tipo dentro del objeto nodo
typedef std::auto_ptr<Tipo> CampoTipo;


#endif

